package com.mustang.core.client.type;
import com.mustang.core.client.GQuery;

public abstract class Func
{
	private static final String RETURN = "return";
	// the reference to the holder instance of this
	protected GQuery holder;
	// Accept any type of the return
	protected JsObject returnValue = JsObject.$O();
	// Accept any type of the pass in parameters
	protected JsObject arguments = JsObject.$O();

	public Func()
	{
	}

	// Public Visibility

	public abstract void process();

	/**
	 * Get the holder of this function
	 * 
	 * @return
	 */
	public GQuery holder()
	{
		return holder;
	}

	/**
	 * Get the argument
	 * 
	 * @param <T>
	 *          argument type
	 * @param key
	 *          argument name
	 * @return the argument value
	 */
	public int getIntArgument(String key)
	{
		return arguments.getInt(key);
	}
	
	public boolean getBooleanArgument(String key)
	{
		return arguments.getBoolean(key);
	}
	
	public double getDoubleArgument(String key)
	{
		return arguments.getDouble(key);
	}
	
	public String getStringArgument(String key)
	{
		return arguments.getString(key);
	}
	
	public JsObject getJsObjectArgument(String key)
	{
		return arguments.getJsObject(key);
	}
	
	public JsArray<?> getJsArrayArgument(String key)
	{
		return arguments.getJsArray(key);
	}

	/**
	 * Set the return value
	 * 
	 * @param <T>
	 *          return type
	 * @param value
	 *          the value should be return from the function
	 */
	public void setReturn(int value)
	{
		returnValue.set(RETURN, value);
	}
	
	public void setReturn(double value)
	{
		returnValue.set(RETURN, value);
	}
	
	public void setReturn(String value)
	{
		returnValue.set(RETURN, value);
	}
	
	public void setReturn(boolean value)
	{
		returnValue.set(RETURN, value);
	}
	
	public void setReturn(JsObject value)
	{
		returnValue.set(RETURN, value);
	}
	
	public void setReturn(JsArray<?> value)
	{
		returnValue.set(RETURN, value);
	}
	
	public int returnInt()
	{
		return returnValue.getInt(RETURN);
	}

	public String returnString()
	{
		return returnValue.getString(RETURN);
	}

	public double returnDouble()
	{
		return returnValue.getDouble(RETURN);
	}

	public boolean returnBoolean()
	{
		return returnValue.getBoolean(RETURN);
	}

	public JsObject returnJsObject()
	{
		return returnValue.getJsObject(RETURN);
	}

	public JsArray<?> returnJsArray()
	{
		return returnValue.getJsArray(RETURN);
	}
	

	// Package Visibility
	/**
	 * Set the argument for key,these methods are all used by GQuery JSNI call ,since <T> is not supported in JSNI methods
	 * 
	 * @param key
	 *          argument name
	 * @param value
	 *          argument value
	 */
	void setArgument(String key, int value)
	{
		arguments.set(key, value);
	}

	void setArgument(String key, double value)
	{
		arguments.set(key, value);
	}

	void setArgument(String key, String value)
	{
		arguments.set(key, value);
	}

	void setArgument(String key, boolean value)
	{
		arguments.set(key, value);
	}
	
	void setArgument(String key, JsObject value)
	{
		arguments.set(key, value);
	}

	/**
	 * Apply the function
	 * 
	 * @param <T>
	 * @param holder
	 * @return
	 */
	void apply(GQuery holder)
	{
		this.holder = holder;
		this.process();
	}

}
